home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / lists / mint / l_1599 / 1227 < prev    next >
Encoding:
Internet Message Format  |  1994-08-27  |  12.9 KB

  1. From: Kay Roemer <roemer@informatik.uni-frankfurt.de>
  2. Posted-Date: Mon, 21 Mar 94 9:25:12 MEZ
  3. Received-Date: Mon, 21 Mar 94 09:25:12 +0100
  4. Message-Id: <9403210825.AA05871@hera.rbi.informatik.uni-frankfurt.de>
  5. Subject: addroottimeout() for Mint 1.10
  6. To: ersmith@netcom.com
  7. Date: Mon, 21 Mar 94 9:25:12 MEZ
  8. Mailer: Elm [revision: 70.85]
  9.  
  10. The following diffs relative to Mint 1.10 implement the function
  11.  
  12. TIMEOUT *addroottimeout (long delta, void (*func)(long), short flags);
  13.  
  14. which is accessible by loadable device drivers and file systems trough
  15. `struct kerinfo'.
  16.  
  17. It is used to attach a timeout to happen in `delta' milliseconds to
  18. the `root' process, ie MiNT.
  19.  
  20. Remember that `addtimeout' attaches the timeout to the process which
  21. was active when addtimeout was called. This means the timeout will be
  22. cancelled if this process exits.
  23.  
  24. Timeouts set with `addroottimeout' wont be cancelled this way. They
  25. always happen unless you cancel them explicitely with `canceltimeout'.
  26.  
  27. Thus addroottimeout can be used by device drivers and file systems
  28. to maintain priodic tasks. Note that the timeout function can use
  29. all the functions provided by `struct kerinfo' (a separate process
  30. can't)!
  31.  
  32. `addroottimeout' takes an additional argument `flags'. Currently
  33. only bit #0 is used. All other bits are reserved and have currently
  34. no meaning.
  35.  
  36. The meaning of bit #0 is:
  37.  
  38. bit #0 set: `addrootimeout' is called from interrupt. This makes
  39. `addroottimeout' avoid kmalloc() and use statically allocated
  40. memory for the TIMEOUT structure instead.
  41.  
  42. bit #0 clear: not called from interrupt, can use kmalloc().
  43.  
  44. Thus (if bit #0 of flags is set), `addroottimeout' can be called from
  45. interrupt. This makes it extremly useful for interrupt driven device
  46. drivers, for instance serial ones.
  47.  
  48. Let us assume a driver receives characters interrupt driven. It maintains
  49. a flag `timeout_pending'. If a character arrives and this flag is not
  50. set, the driver adds a timeout using `addroottimeout' with flags&1 == 1,
  51. delta ~ 200 and sets the flag `timeout_pending'.
  52.  
  53. Thus the timeout function will be called in about 200 ms. It resets
  54. the flag `timeout_pending' and then processes the arrived characters,
  55. does some time consuming jobs (sending signals and waking up processes,
  56. for instance) that cannot be done at interrupt time. It may use all the
  57. kernel functions in `struct kerinfo'.
  58.  
  59. This is a only reasonable (no polling) method for hardware device
  60. drivers to use sleep() and wake() instead of nap().
  61.  
  62. `addroottimeout' is also extensively used in MintNet, so I would love
  63. to see it included in Mint 1.11!
  64.  
  65. Note that `addroottimeout' may return NULL when memory is low.
  66.  
  67. As a side effekt, the diffs incorporate a fallback method for `addtimeout'
  68. when kmalloc() is out of memory.
  69.  
  70. I also fixed `checkalarms' to decrease the `when' field of the head of
  71. the timeout list *before* calling the timeout function. Otherwise the
  72. timeout function could install another timeout, whose `when' field is
  73. then wronly decreased.
  74.  
  75. So long,
  76. Kay.
  77.  
  78. --8<----------------------------------------------------
  79. *** file.h.orig    Tue Feb 22 19:30:10 1994
  80. --- file.h    Mon Mar  7 21:43:10 1994
  81. ***************
  82. *** 243,251 ****
  83.   /* functions for adding/cancelling timeouts */
  84.       struct timeout * ARGS_ON_STACK (*addtimeout) P_((long, void (*)()));
  85.       void    ARGS_ON_STACK (*canceltimeout) P_((struct timeout *));
  86.    
  87.   /* reserved for future use */
  88. !     long    res2[7];
  89.   };
  90.   
  91.   /* flags for open() modes */
  92. --- 243,252 ----
  93.   /* functions for adding/cancelling timeouts */
  94.       struct timeout * ARGS_ON_STACK (*addtimeout) P_((long, void (*)()));
  95.       void    ARGS_ON_STACK (*canceltimeout) P_((struct timeout *));
  96. +     struct timeout * ARGS_ON_STACK (*addroottimeout) P_((long, void (*)(), short));
  97.    
  98.   /* reserved for future use */
  99. !     long    res2[6];
  100.   };
  101.   
  102.   /* flags for open() modes */
  103. *** main.c.orig    Fri Feb 11 19:37:16 1994
  104. --- main.c    Tue Feb 22 19:32:52 1994
  105. ***************
  106. *** 193,199 ****
  107.       strnicmp, stricmp, strlwr, strupr, ksprintf,
  108.       ms_time, unixtim, dostim,
  109.       nap, sleep, wake, wakeselect,
  110. !     denyshare, denylock, addtimeout, canceltimeout
  111.   };
  112.   
  113.   /* table of processor frame sizes in _words_ (not used on MC68000) */
  114. --- 193,200 ----
  115.       strnicmp, stricmp, strlwr, strupr, ksprintf,
  116.       ms_time, unixtim, dostim,
  117.       nap, sleep, wake, wakeselect,
  118. !     denyshare, denylock, addtimeout, canceltimeout,
  119. !     addroottimeout
  120.   };
  121.   
  122.   /* table of processor frame sizes in _words_ (not used on MC68000) */
  123. *** proc.h.orig    Tue Feb 22 17:35:32 1994
  124. --- proc.h    Tue Feb 22 17:36:04 1994
  125. ***************
  126. *** 67,72 ****
  127. --- 67,73 ----
  128.       struct proc    *proc;
  129.       long    when;
  130.       void    (*func) P_((struct proc *)); /* function to call at timeout */
  131. +     short    flags;
  132.   } TIMEOUT;
  133.   
  134.   #ifndef GENMAGIC
  135. *** proto.h.orig    Tue Feb 22 19:34:14 1994
  136. --- proto.h    Mon Mar  7 21:42:12 1994
  137. ***************
  138. *** 274,279 ****
  139. --- 274,280 ----
  140.   
  141.   /* timeout.c */
  142.   TIMEOUT * ARGS_ON_STACK addtimeout P_((long delta, void (*func)(PROC *p)));
  143. + TIMEOUT * ARGS_ON_STACK addroottimeout P_((long delta, void (*func)(PROC *p), short flags));
  144.   void ARGS_ON_STACK cancelalltimeouts P_((void));
  145.   void ARGS_ON_STACK canceltimeout P_((TIMEOUT *which));
  146.   void ARGS_ON_STACK timeout P_((void));
  147. *** timeout.c.orig    Sat Feb 19 15:57:00 1994
  148. --- timeout.c    Sat Mar 19 18:30:34 1994
  149. ***************
  150. *** 19,55 ****
  151.   extern short in_kernel;    /* in main.c */
  152.   
  153.   static void unnapme P_((PROC *));
  154.   
  155. ! /*
  156. !  * addtimeout(long delta, void (*func)()): schedule a timeout for the current
  157. !  * process, to take place in "delta" milliseconds. "func" specifies a
  158. !  * function to be called at that time; the function is passed as a parameter
  159. !  * the process for which the timeout was specified (i.e. the value of
  160. !  * curproc at the time addtimeout() was called; note that this is probably
  161. !  * *not* the current process when the timeout occurs).
  162.    */
  163. ! TIMEOUT *tlist;
  164.   
  165. - #define newtimeout() (TIMEOUT *)kmalloc(SIZEOF(TIMEOUT))
  166. - #define disposetimeout(t) kfree(t)
  167.   
  168. ! TIMEOUT * ARGS_ON_STACK
  169. ! addtimeout(delta, func)
  170. !     long delta;
  171. !     void (*func) P_((PROC *));
  172.   {
  173. !     TIMEOUT *t, **prev, *cur;
  174.   
  175. !     t = newtimeout();
  176.   
  177. ! /* BUG: we should have some fallback mechanism for timeouts when the
  178. !    kernel memory is exhausted
  179. !  */
  180. !     assert(t);
  181.   
  182. !     t->proc = curproc;
  183. !     t->func = func;
  184.   
  185.       cur = tlist;
  186.       prev = &tlist;
  187. --- 19,80 ----
  188.   extern short in_kernel;    /* in main.c */
  189.   
  190.   static void    unnapme P_((PROC *));
  191. + static TIMEOUT    *newtimeout P_((short));
  192. + static void    disposetimeout P_((TIMEOUT *));
  193. + static void    inserttimeout P_ ((TIMEOUT *, long));
  194. + #define TIMEOUTS    20    /* # of static timeout structs */
  195. + #define TIMEOUT_USED    0x01    /* timeout struct is in use */
  196. + #define TIMEOUT_STATIC    0x02    /* this is a static timeout */
  197.   
  198. ! /* This gets implizitly initialized to zero, thus the flags are
  199. !  * set up correctly.
  200.    */
  201. ! static TIMEOUT timeouts[TIMEOUTS] = { { 0, }, };
  202. ! TIMEOUT *tlist = NULL;
  203.   
  204.   
  205. ! static TIMEOUT *
  206. ! newtimeout(fromlist)
  207. !     short fromlist;
  208.   {
  209. !     TIMEOUT *t;
  210. !     short i, sr;
  211.   
  212. !     if (!fromlist) {
  213. !         t = kmalloc(SIZEOF(TIMEOUT));
  214. !         if (t) {
  215. !             t->flags = 0;
  216. !             return t;
  217. !         }
  218. !     }
  219. !     sr = spl7();
  220. !     for (i = 0; i < TIMEOUTS; ++i) {
  221. !         if (!(timeouts[i].flags & TIMEOUT_USED)) {
  222. !             timeouts[i].flags |= (TIMEOUT_STATIC|TIMEOUT_USED);
  223. !             spl(sr);
  224. !             return &timeouts[i];
  225. !         }
  226. !     }
  227. !     spl(sr);
  228. !     return 0;
  229. ! }
  230.   
  231. ! static void
  232. ! disposetimeout(t)
  233. !     TIMEOUT *t;
  234. ! {
  235. !     if (t->flags & TIMEOUT_STATIC) t->flags &= ~TIMEOUT_USED;
  236. !     else kfree(t);
  237. ! }
  238.   
  239. ! static void
  240. ! inserttimeout(t, delta)
  241. !     TIMEOUT *t;
  242. !     long delta;
  243. ! {
  244. !     TIMEOUT **prev, *cur;
  245. !     short sr = spl7();
  246.   
  247.       cur = tlist;
  248.       prev = &tlist;
  249. ***************
  250. *** 59,65 ****
  251.               t->next = cur;
  252.               t->when = delta;
  253.               *prev = t;
  254. !             return t;
  255.           }
  256.           delta -= cur->when;
  257.           prev = &cur->next;
  258. --- 84,91 ----
  259.               t->next = cur;
  260.               t->when = delta;
  261.               *prev = t;
  262. !             spl(sr);
  263. !             return;
  264.           }
  265.           delta -= cur->when;
  266.           prev = &cur->next;
  267. ***************
  268. *** 69,74 ****
  269. --- 95,167 ----
  270.       t->when = delta;
  271.       t->next = cur;
  272.       *prev = t;
  273. +     spl(sr);
  274. + }
  275. +     
  276. + /*
  277. +  * addtimeout(long delta, void (*func)()): schedule a timeout for the current
  278. +  * process, to take place in "delta" milliseconds. "func" specifies a
  279. +  * function to be called at that time; the function is passed as a parameter
  280. +  * the process for which the timeout was specified (i.e. the value of
  281. +  * curproc at the time addtimeout() was called; note that this is probably
  282. +  * *not* the current process when the timeout occurs).
  283. +  *
  284. +  * NOTE: if kernel memory is low, newtimeout() will try to get a statically
  285. +  * allocated timeout struct (fallback method).
  286. +  */
  287. + TIMEOUT * ARGS_ON_STACK
  288. + addtimeout(delta, func)
  289. +     long delta;
  290. +     void (*func) P_((PROC *));
  291. + {
  292. +     TIMEOUT *t;
  293. +     t = newtimeout(0);
  294. + /* BUG: we should have some fallback mechanism for timeouts when the
  295. +    kernel memory is exhausted
  296. +  */
  297. +     assert(t);
  298. +     t->proc = curproc;
  299. +     t->func = func;
  300. +     inserttimeout(t, delta);
  301. +     return t;
  302. + }
  303. + /*
  304. +  * addroottimeout(long delta, void (*)(PROC *), short flags);
  305. +  * Same as addtimeout(), except that the timeout is attached to Pid 0 (MiNT).
  306. +  * This means the timeout won't be cancelled if the process which was
  307. +  * running at the time addroottimeout() was called exits.
  308. +  *
  309. +  * Currently only bit 0 of `flags' is used. Meaning:
  310. +  * Bit 0 set: Call from interrupt (cannot use kmalloc, use statically
  311. +  *    allocated `struct timeout' instead).
  312. +  * Bit 0 clear: Not called from interrupt, can use kmalloc.
  313. +  *
  314. +  * Thus addroottimeout() can be called from interrupts (bit 0 of flags set),
  315. +  * which makes it *extremly* useful for device drivers.
  316. +  * A serial device driver would make an addroottimeout(0, check_keys, 1)
  317. +  * if some bytes have arrived.
  318. +  * check_keys() is then called at the next context switch, can use all
  319. +  * the kernel functions and can do time cosuming jobs.
  320. +  */
  321. + TIMEOUT * ARGS_ON_STACK
  322. + addroottimeout(delta, func, flags)
  323. +     long delta;
  324. +     void (*func) P_((PROC *));
  325. +     short flags;
  326. + {
  327. +     TIMEOUT *t;
  328. +     t = newtimeout(flags & 1);
  329. +     if (!t) return NULL;
  330. +     t->proc = rootproc;
  331. +     t->func = func;
  332. +     inserttimeout(t, delta);
  333.       return t;
  334.   }
  335.   
  336. ***************
  337. *** 82,87 ****
  338. --- 175,181 ----
  339.   {
  340.       TIMEOUT *cur, **prev, *old;
  341.       long delta;
  342. +     short sr = spl7 ();
  343.   
  344.       cur = tlist;
  345.       prev = &tlist;
  346. ***************
  347. *** 91,103 ****
  348. --- 185,203 ----
  349.               old = cur;
  350.               *prev = cur = cur->next;
  351.               if (cur) cur->when += delta;
  352. +             spl(sr);
  353.               disposetimeout(old);
  354. +             sr = spl7();
  355. +         /* ++kay: just in case an interrupt handler installed a
  356. +          * timeout right after `prev' and before `cur' */
  357. +             cur = *prev;
  358.           }
  359.           else {
  360.               prev = &cur->next;
  361.               cur = cur->next;
  362.           }
  363.       }
  364. +     spl (sr);
  365.   }
  366.   
  367.   /*
  368. ***************
  369. *** 115,133 ****
  370.       TIMEOUT *this;
  371.   {
  372.       TIMEOUT *cur, **prev;
  373.   
  374.       prev = &tlist;
  375.       for (cur = tlist; cur; cur = cur->next) {
  376. !         if (cur == this && cur->proc == curproc) {
  377.               *prev = cur->next;
  378.               if (cur->next) {
  379.                   cur->next->when += this->when;
  380.               }
  381.               disposetimeout(this);
  382. !             break;
  383.           }
  384.           prev = &cur->next;
  385.       }
  386.   }
  387.   
  388.   /*
  389. --- 215,237 ----
  390.       TIMEOUT *this;
  391.   {
  392.       TIMEOUT *cur, **prev;
  393. +     short sr = spl7();
  394.       
  395.       prev = &tlist;
  396.       for (cur = tlist; cur; cur = cur->next) {
  397. !         if (cur == this &&
  398. !             (cur->proc == curproc || cur->proc == rootproc)) {
  399.               *prev = cur->next;
  400.               if (cur->next) {
  401.                   cur->next->when += this->when;
  402.               }
  403. +             spl (sr);
  404.               disposetimeout(this);
  405. !             return;
  406.           }
  407.           prev = &cur->next;
  408.       }
  409. +     spl(sr);
  410.   }
  411.   
  412.   /*
  413. ***************
  414. *** 170,175 ****
  415. --- 274,280 ----
  416.       long delta;
  417.       void (*evnt) P_((PROC *));
  418.       TIMEOUT *old;
  419. +     short sr;
  420.   
  421.   /* do the once per second things */
  422.       while (our_clock < 0) {
  423. ***************
  424. *** 180,201 ****
  425.           reset_priorities();
  426.       }
  427.   
  428.   /* see if there are outstanding timeout requests to do */
  429.       while (tlist && ((delta = tlist->when) <= 0)) {
  430.           p = tlist->proc;
  431. -         TRACE(("doing timeout code for pid %d", p->pid));
  432.           evnt = tlist->func;
  433.           old = tlist;
  434.           tlist = tlist->next;
  435. -         disposetimeout(old);
  436. -     /* call the timeout function */
  437. -         (*evnt)(p);
  438.   /* if delta < 0, it's possible that the time has come for the next timeout
  439. !    to occur */
  440.           if (tlist)
  441.               tlist->when += delta;
  442.       }
  443.   }
  444.   
  445.   /*
  446. --- 285,313 ----
  447.           reset_priorities();
  448.       }
  449.   
  450. +     sr = spl7();
  451.   /* see if there are outstanding timeout requests to do */
  452.       while (tlist && ((delta = tlist->when) <= 0)) {
  453.           p = tlist->proc;
  454.           evnt = tlist->func;
  455.           old = tlist;
  456.           tlist = tlist->next;
  457.   /* if delta < 0, it's possible that the time has come for the next timeout
  458. !  * to occur.
  459. !  * ++kay: moved this before the timeout fuction is called, in case the
  460. !  * timeout function installes a new timeout. */
  461.           if (tlist)
  462.               tlist->when += delta;
  463. +         spl(sr);
  464. + /* ++kay: debug output at spl7 hangs the system, so moved it here */
  465. +         TRACE(("doing timeout code for pid %d", p->pid));
  466. +         disposetimeout(old);
  467. +     /* call the timeout function */
  468. +         (*evnt)(p);
  469. +         sr = spl7();
  470.       }
  471. +     spl(sr);
  472.   }
  473.   
  474.   /*
  475. --8<----------------------------------------------------
  476.